﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using System.Net;
using System.Net.Sockets;
using OrchardSystemServer.Net;
using System.Threading;
using OrchardSystemServer.Account;
using OrchardSystemServer.Log;
using OrchardSystemServer.Security;
using System.Reflection;

namespace OrchardSystemServer
{
    public partial class OrchardSystem : Form
    {

        private TcpListener tcpListener;

        /// <summary>
        /// 输出日志到ListBox
        /// </summary>
        private LogToListBox log;

        /// <summary>
        /// 显示当前连接数
        /// </summary>
        private LogToListBox currentUser;

        /// <summary>
        /// 管理连接的用户信息以及服务器信息
        /// </summary>
        ConnectionManager mUserManager;

        /// <summary>
        /// 窗体是否显示
        /// </summary>
        public bool isShow = true;

        public OrchardSystem()
        {
            InitializeComponent();
            toolStripStatusLabel.Text = "Copyright China Aricultural University,CIEE,WangYun,Graduation Thesis" + "\n编译时间:" + System.IO.File.GetLastWriteTime(this.GetType().Assembly.Location);
            timerState.Start();
            toolStripStatusLabelCurrentTime.Text = "当前时间:\n" + DateTime.Now.ToString().Replace('/', '-');
            this.Text = AssemblyProduct;
            buttonStop.Enabled = false;
            ArrayList list = NetHelper.GetLocalIPv4Address();//获得本地的IPV4地址
            comboBoxServerIp.DataSource = list;
            log = new LogToListBox(listBoxLog);
            currentUser = new LogToListBox(listBoxUserList);
            mUserManager = new ConnectionManager();
            UpdateConnectionPanel();
        }




        /// <summary>
        /// 接收客户端连接
        /// </summary>
        private void ListenClientConnect()
        {
            TcpClient newClient = null;
            while (true)
            {
                try
                {
                    newClient = tcpListener.AcceptTcpClient();
                }
                catch
                {
                    //当单击‘停止监听’或者退出此窗体时 AcceptTcpClient() 会产生异常
                    //因此可以利用此异常退出循环
                    break;
                }
                //每接收一个客户端连接，就创建一个对应的线程循环接收该客户端发来的信息；
                ConnectionClient user = new ConnectionClient(newClient);
                Thread threadReceive = new Thread(ReceiveData);
                threadReceive.Start(user);
                mUserManager.UserList.Add(user);
                log.AddItemWithTime(string.Format("[{0}]连接到服务器", user.UserSocketDescription + "," + user.UserName));
                //SendToClient(user,"401#welcome to orchard system!");
                log.AddItemWithTime(string.Format("当前连接用户数：{0}", mUserManager.UserList.Count));
                UpdateConnectionPanel();
            }

        }


        /// <summary>
        /// 处理接收的客户端信息
        /// </summary>
        /// <param name="userState">客户端信息</param>
        private void ReceiveData(object userState)
        {
            ConnectionClient user = (ConnectionClient)userState;
            String clientInfo = user.UserSocketDescription;
            TcpClient client = user.Client;
            while (true)
            {
                string receiveString = null;
                try
                {
                    receiveString = user.reader.ReadLine();
                }
                catch (Exception)
                {
                    log.AddItemWithTime(string.Format("[{0}]断开连接,ex", clientInfo));
                    RemoveUser(user, false);
                    UpdateConnectionPanel();
                    break;

                }
                log.AddItemWithTime(string.Format("收到[{0}]消息：{1}", user.UserSocketDescription, receiveString));
                if (receiveString == null || receiveString.Equals(""))
                {
                    log.AddItemWithTime("指令不能为空!");
                    SendToClient(user, "指令不能为空!");
                    return;
                }

                string[] splitString = receiveString.Split('#');
                int length = splitString.Length;

                string msg = "";
                string machineId = "";
                string orchardId = "";
                if (!splitString[0].Equals("login") && splitString.Length >= 2)
                {
                    string token = splitString[1];
                    if (UserValidation.IsUserLogined(token))
                    {
                        switch (splitString[0])
                        {
                            case "gettask"://获得任务
                                machineId = splitString[2];
                                orchardId = "";
                                if (user.commandExecutor.GetTask(machineId, ref orchardId))
                                {

                                    msg = "200#" + orchardId;
                                }
                                else
                                {
                                    msg = "401#" + user.commandExecutor.LastErrorMessage;
                                }

                                break;
                            case "getboundary"://获得果园边界信息
                                orchardId = splitString[2];
                                string getboundary = "";
                                if (user.commandExecutor.GetBoundary(orchardId, ref getboundary))
                                {

                                    msg = "200#" + getboundary;
                                }
                                else
                                {
                                    msg = "401#" + user.commandExecutor.LastErrorMessage;
                                }
                                break;
                            case "gettrees"://获得果树信息
                                orchardId = splitString[2];
                                string gettrees = "";
                                if (user.commandExecutor.GetTrees(orchardId, ref gettrees))
                                {
                                    msg = "200#" + gettrees;
                                }
                                else
                                {
                                    msg = "401#" + user.commandExecutor.LastErrorMessage;
                                }
                                break;
                            case "updateboundary"://更新边界
                                orchardId = splitString[2];
                                string updateboundary = splitString[3];
                                if (user.commandExecutor.UpdateBoundary(orchardId, updateboundary))
                                {

                                    msg = "200#果园" + orchardId + "增加边界成功";
                                }
                                else
                                {
                                    msg = "401#" + user.commandExecutor.LastErrorMessage;
                                }
                                break;
                            case "updatetrees"://更新果树
                                orchardId = splitString[2];
                                string updatetrees = splitString[3];
                                if (user.commandExecutor.UpdateTrees(orchardId, updatetrees))
                                {

                                    msg = "200#果园" + orchardId + "增加果树基本信息成功";
                                }
                                else
                                {
                                    msg = "401#" + user.commandExecutor.LastErrorMessage;
                                }
                                break;
                            case "addtreescollect"://增加采集的果树信息
                                string addTreesCollect = splitString[2];
                                if (user.commandExecutor.AddTreeCollectInformation(addTreesCollect))
                                {

                                    msg = "200#果园" + orchardId + "上传果树采集信息成功";
                                }
                                else
                                {
                                    msg = "401#" + user.commandExecutor.LastErrorMessage;
                                }
                                break;
                            default:
                                msg = "无法解析的命令:" + receiveString;
                                break;
                        }
                    }
                    else
                    {
                        msg = "402#登录凭据已失效,请重新登录";
                    }
                }
                else
                {
                    if (splitString[0].Equals("login"))
                    {
                        if (length < 3)
                            msg = "402#登录命令格式有误，应为login#username#password";
                        else
                        {
                            user.UserName = splitString[1];
                            String token = "";
                            if (user.commandExecutor.UserLogin(user.UserName, splitString[2], ref token))
                                msg = "200#" + token + "#登录成功";
                            else
                            {
                                msg = "400#" + user.commandExecutor.LastErrorMessage;

                            }
                        }
                    }
                    else if (splitString[0].Equals("logout"))
                    {
                        RemoveUser(user, true);
                        return;
                    }
                    else
                    {
                        msg = "无法解析的命令:" + receiveString;
                    }
                }
                SendToClient(user, msg);
            }
        }


        /// <summary>
        /// 发送 message 给 user
        /// </summary>
        /// <param name="user">指定发给哪个用户</param>
        /// <param name="message">信息内容</param>
        private void SendToClient(ConnectionClient user, string message)
        {
            try
            {
                //将字符串写入网络流，此方法会自动附加字符串长度前缀
                user.writer.Write(message + "\r\n");
                user.writer.Flush();
                log.AddItemWithTime(string.Format("向[{0}]发送消息：{1}", user.UserSocketDescription + "," + user.UserName, message));
            }
            catch
            {
                log.AddItemWithTime(string.Format("向[{0}]发送信息失败", user.UserSocketDescription + "," + user.UserName));
            }
        }

        /// <summary>
        /// 移除用户
        /// </summary>
        /// <param name="user">指定要移除的用户</param>
        private void RemoveUser(ConnectionClient user, bool isNormal)
        {
            mUserManager.UserList.Remove(user);
            if (isNormal)
                log.AddItemWithTime(string.Format("{0}已断开连接", user.UserSocketDescription + "," + user.UserName));
            log.AddItemWithTime(string.Format("当前连接用户数：{0}", mUserManager.UserList.Count));
            user.Close();
            user = null;
            UpdateConnectionPanel();
        }





        /// <summary>
        /// 启动监听
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonStart_Click(object sender, EventArgs e)
        {
            mUserManager.ServerIP = comboBoxServerIp.SelectedValue.ToString();
            mUserManager.ServerPort = Convert.ToInt32(textBoxPort.Text);

            tcpListener = new TcpListener(IPAddress.Parse(mUserManager.ServerIP), mUserManager.ServerPort);
            tcpListener.Start();
            log.AddItemWithTime(string.Format("开始在{0}:{1}监听客户连接", mUserManager.ServerIP, mUserManager.ServerPort));
            //创建一个线程监客户端连接请求
            Thread myThread = new Thread(ListenClientConnect);
            myThread.Start();
            buttonStart.Enabled = false;
            buttonStop.Enabled = true;
        }

        /// <summary>
        /// 停止监听
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonStop_Click(object sender, EventArgs e)
        {
            log.AddItemWithTime("开始停止服务，并依次使用户退出！");

            for (int i = mUserManager.UserList.Count - 1; i >= 0; i--)
            {
                RemoveUser(mUserManager.UserList[i], true);
            }
            //通过停止监听让 myListener.AcceptTcpClient() 产生异常退出监听线程
            tcpListener.Stop();
            buttonStart.Enabled = true;
            buttonStop.Enabled = false;
            log.AddItemWithTime("服务器已停止服务！");
        }

        private void OrchardSystem_FormClosed(object sender, FormClosedEventArgs e)
        {
            if (tcpListener != null)
                buttonStop.PerformClick();    //引发 btn_Stop 的Click事件
        }

        /// <summary>
        /// 更新在线连接信息面板
        /// </summary>
        public void UpdateConnectionPanel()
        {
            currentUser.ClearItem();
            currentUser.AddItem(string.Format("当前在线连接数:{0}", mUserManager.UserList.Count));
            for (int i = 0; i < mUserManager.UserList.Count; i++)
            {
                currentUser.AddItem(mUserManager.UserList[i].UserSocketDescription);
            }
        }

        /// <summary>
        /// 清空日志
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void 清空ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            log.ClearItem();
        }

        /// <summary>
        /// 设置listbox第一项为红色
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void listBoxUserList_DrawItem(object sender, DrawItemEventArgs e)
        {
            if (e.Index < 0)
                return;
            // 为listbox的每一项绘制背景
            e.DrawBackground();
            // 设置默认颜色为黑色
            Brush myBrush = Brushes.Black;

            // 设置每一项的颜色
            switch (e.Index)
            {
                case 0://设置第一项为红色
                    myBrush = Brushes.Red;
                    break;
            }

            // 绘制listbox中的每一项
            e.Graphics.DrawString(listBoxUserList.Items[e.Index].ToString(),
                e.Font, myBrush, e.Bounds, StringFormat.GenericDefault);
            // 绘制被选中项选中边框
            e.DrawFocusRectangle();
        }

        private int WM_SYSCOMMAND = 0x112;
        //private long SC_MAXIMIZE = 0xF030;
        private long SC_MINIMIZE = 0xF020;
        private long SC_CLOSE = 0xF060;
        protected override void WndProc(ref Message m)
        {
            if (m.Msg == WM_SYSCOMMAND)
            {
                if (m.WParam.ToInt64() == SC_MINIMIZE)
                {
                    ToolStripMenuItemShowOrHide.Text = ShowOrHide();
                    notifyIcon.BalloonTipTitle = "提示";
                    notifyIcon.BalloonTipText =AssemblyProduct+"最小化到此处";
                    notifyIcon.ShowBalloonTip(1000);
                    return;
                } if (m.WParam.ToInt64() == SC_CLOSE)
                {
                    if (DialogResult.Yes != MessageBox.Show("确定退出《"+AssemblyProduct+"》?", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Information))
                    {
                        return;
                    }
                }
            }
            base.WndProc(ref m);
        }

        public string AssemblyProduct
        {
            get
            {
                object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), false);
                if (attributes.Length == 0)
                {
                    return "";
                }
                return ((AssemblyProductAttribute)attributes[0]).Product;
            }
        }

        public string ShowOrHide()
        {
            string result = "";
            if (isShow)
            {
                result = "显示";
                this.Hide();
            }
            else
            {
                result = "隐藏"; 
                this.Show();
            }
            isShow = !isShow;
            return result;
        }

        private void ToolStripMenuItemShowOrHide_Click(object sender, EventArgs e)
        {
            ToolStripMenuItemShowOrHide.Text =ShowOrHide();
        }

        private void buttonSettings_Click(object sender, EventArgs e)
        {
            Setting setting = new Setting();
            setting.ShowDialog();
        }

        private void timerState_Tick(object sender, EventArgs e)
        {
            toolStripStatusLabelCurrentTime.Text = "当前时间:\n" + DateTime.Now.ToString().Replace('/','-');
        }
    }

}